/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-08-06     RealThread   first version
 */
#include <rtthread.h>
#include <board.h>
#include <drv_common.h>

#include "drv_qspi.h"
#include "spi_flash_sfud.h"

#include "mc_type.h" //todo 后续优化

void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);

RT_WEAK void rt_hw_board_init()
{
    extern void hw_board_init(char *clock_src, int32_t clock_src_freq, int32_t clock_target_freq);

    /* Heap initialization */
#if defined(RT_USING_HEAP)
    rt_system_heap_init((void *) HEAP_BEGIN, (void *) HEAP_END);
#endif

    hw_board_init(BSP_CLOCK_SOURCE, BSP_CLOCK_SOURCE_FREQ_MHZ, BSP_CLOCK_SYSTEM_FREQ_MHZ);

    /* Set the shell console output device */
#if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE)
    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif

    /* Board underlying hardware initialization */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif

}


#define FLASH_CS     GET_PIN(B, 6)
static int rt_hw_spi_flash_init(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    stm32_qspi_bus_attach_device("qspi1", "qspi10", FLASH_CS, 2,NULL,NULL);

    if (RT_NULL == rt_sfud_flash_probe("GD25Q64", "qspi10"))
    {
        return -RT_ERROR;
    };

    return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);

/**
* @brief QSPI MSP Initialization
* This function configures the hardware resources used in this example
* @param hqspi: QSPI handle pointer
* @retval None
*/
void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hqspi->Instance==QUADSPI)
  {
  /* USER CODE BEGIN QUADSPI_MspInit 0 */

  /* USER CODE END QUADSPI_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_QSPI_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**QUADSPI GPIO Configuration
    PB2     ------> QUADSPI_CLK
    PC9     ------> QUADSPI_BK1_IO0
    PC10     ------> QUADSPI_BK1_IO1
    PB6     ------> QUADSPI_BK1_NCS
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_QSPI;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_QSPI;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF10_QSPI;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN QUADSPI_MspInit 1 */

  /* USER CODE END QUADSPI_MspInit 1 */
  }

}

/**
* @brief QSPI MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hqspi: QSPI handle pointer
* @retval None
*/
void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef* hqspi)
{
  if(hqspi->Instance==QUADSPI)
  {
  /* USER CODE BEGIN QUADSPI_MspDeInit 0 */

  /* USER CODE END QUADSPI_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_QSPI_CLK_DISABLE();

    /**QUADSPI GPIO Configuration
    PB2     ------> QUADSPI_CLK
    PC9     ------> QUADSPI_BK1_IO0
    PC10     ------> QUADSPI_BK1_IO1
    PB6     ------> QUADSPI_BK1_NCS
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_2|GPIO_PIN_6);

    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_9|GPIO_PIN_10);

  /* USER CODE BEGIN QUADSPI_MspDeInit 1 */

  /* USER CODE END QUADSPI_MspDeInit 1 */
  }

}

//extern TIM_HandleTypeDef htim1;
///**
//  * @brief This function handles TIM1 update interrupt and TIM10 global interrupt.
//  */
//void TIM1_UP_TIM10_IRQHandler(void)
//{
//  /* USER CODE BEGIN TIM1_UP_TIM10_IRQn 0 */
//
//  /* USER CODE END TIM1_UP_TIM10_IRQn 0 */
//  HAL_TIM_IRQHandler(&htim1);
//  /* USER CODE BEGIN TIM1_UP_TIM10_IRQn 1 */
//
//  /* USER CODE END TIM1_UP_TIM10_IRQn 1 */
//}
//
///**
//  * @brief This function handles TIM1 capture compare interrupt.
//  */
//void TIM1_CC_IRQHandler(void)
//{
//  /* USER CODE BEGIN TIM1_CC_IRQn 0 */
//
//  /* USER CODE END TIM1_CC_IRQn 0 */
//  HAL_TIM_IRQHandler(&htim1);
//  /* USER CODE BEGIN TIM1_CC_IRQn 1 */
//
//  /* USER CODE END TIM1_CC_IRQn 1 */
//}
//
//
///**
//  * @brief TIM1 Initialization Function
//  * @param None
//  * @retval None
//  */
//static void MX_TIM1_Init(void)
//{
//
//  /* USER CODE BEGIN TIM1_Init 0 */
//
//  /* USER CODE END TIM1_Init 0 */
//
//  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
//  TIM_MasterConfigTypeDef sMasterConfig = {0};
//  TIM_OC_InitTypeDef sConfigOC = {0};
//  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
//
//  /* USER CODE BEGIN TIM1_Init 1 */
//
//  /* USER CODE END TIM1_Init 1 */
//  htim1.Instance = TIM1;
//  htim1.Init.Prescaler = 9;
//  htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED3;
//  htim1.Init.Period = 999;
//  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
//  htim1.Init.RepetitionCounter = 0;
//  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
//  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
//  {
//    Error_Handler();
//  }
//  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
//  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
//  {
//    Error_Handler();
//  }
//  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
//  {
//    Error_Handler();
//  }
//  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
//  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
//  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
//  {
//    Error_Handler();
//  }
//  sConfigOC.OCMode = TIM_OCMODE_PWM1;
//  sConfigOC.Pulse = 1000;
//  sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
//  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_LOW;
//  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
//  sConfigOC.OCIdleState = TIM_OCIDLESTATE_SET;
//  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_SET;
//  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
//  {
//    Error_Handler();
//  }
//  sConfigOC.Pulse = 1000;
//  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
//  {
//    Error_Handler();
//  }
//  sConfigOC.Pulse = 1000;
//  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
//  {
//    Error_Handler();
//  }
//  sConfigOC.OCMode = TIM_OCMODE_PWM1;
//  sConfigOC.Pulse = 1000;
//  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
//  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
//  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
//  {
//    Error_Handler();
//  }
//  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
//  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
//  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
//  sBreakDeadTimeConfig.DeadTime = 240;//500ns todo
//  sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE;
//  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
//  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
//  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
//  {
//    Error_Handler();
//  }
//  /* USER CODE BEGIN TIM1_Init 2 */
//
//  /* USER CODE END TIM1_Init 2 */
//  HAL_TIM_MspPostInit(&htim1);
//
////soong
//  LL_TIM_OC_SetCompareCH1(htim1.Instance, 1000);
//  HAL_TIM_PWM_Start_IT(&htim1,TIM_CHANNEL_1);
//  HAL_TIMEx_PWMN_Start_IT(&htim1,TIM_CHANNEL_1);
//
//  LL_TIM_OC_SetCompareCH2(htim1.Instance, 1000);
//  HAL_TIM_PWM_Start_IT(&htim1,TIM_CHANNEL_2);
//  HAL_TIMEx_PWMN_Start_IT(&htim1,TIM_CHANNEL_2);
//
//  LL_TIM_OC_SetCompareCH3(htim1.Instance, 1000);
//  HAL_TIM_PWM_Start_IT(&htim1,TIM_CHANNEL_3);
//  HAL_TIMEx_PWMN_Start_IT(&htim1,TIM_CHANNEL_3);
//}
//INIT_BOARD_EXPORT(MX_TIM1_Init);
////INIT_COMPONENT_EXPORT(MX_TIM1_Init);
//
//void pwmstart(void)
//{
//    HAL_TIM_Base_Start_IT(&htim1);
//    HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_3);
//    HAL_TIMEx_PWMN_Start_IT(&htim1, TIM_CHANNEL_3);
//}
//MSH_CMD_EXPORT(pwmstart, init TIM1 pwmout);
//
//uint16_t global_count = 0;
//void pwmctrl(uint8_t argc, char **argv)
//{
//
//#define CMD_PROBE_INDEX               0
//#define CMD_READ_INDEX                1
//#define CMD_WRITE_INDEX               2
//#define CMD_ERASE_INDEX               3
//#define CMD_RW_STATUS_INDEX           4
//#define CMD_BENCH_INDEX               5
//    size_t i = 0;
//    const char* sf_help_info[] = {
//            [CMD_PROBE_INDEX]     = "sf probe [spi_device]           - probe and init SPI flash by given 'spi_device'",
//            [CMD_READ_INDEX]      = "sf read addr size               - read 'size' bytes starting at 'addr'",
//            [CMD_WRITE_INDEX]     = "sf write addr data1 ... dataN   - write some bytes 'data' to flash starting at 'addr'",
//            [CMD_ERASE_INDEX]     = "sf erase addr size              - erase 'size' bytes starting at 'addr'",
//            [CMD_RW_STATUS_INDEX] = "sf status [<volatile> <status>] - read or write '1:volatile|0:non-volatile' 'status'",
//            [CMD_BENCH_INDEX]     = "sf bench                        - full chip benchmark. DANGER: It will erase full chip!",
//    };
////控制pwm输出通道、频率（暂不控制，定频10Khz）、占空比、重复次数
//    if (argc < 4)
//    {
//        rt_kprintf("Usage:\n");
//        for (i = 0; i < sizeof(sf_help_info) / sizeof(char*); i++)
//        {
//            rt_kprintf("%s\n", sf_help_info[i]);
//        }
//        rt_kprintf("\n");
//    }
//    else
//    {
//        HAL_TIM_PWM_Stop_IT(&htim1,TIM_CHANNEL_1);
//        HAL_TIM_PWM_Stop_IT(&htim1,TIM_CHANNEL_2);
//        HAL_TIM_PWM_Stop_IT(&htim1,TIM_CHANNEL_3);
//        HAL_TIMEx_PWMN_Stop_IT(&htim1,TIM_CHANNEL_1);
//        HAL_TIMEx_PWMN_Stop_IT(&htim1,TIM_CHANNEL_2);
//        HAL_TIMEx_PWMN_Stop_IT(&htim1,TIM_CHANNEL_3);
//
//        const char *operator = argv[1];
//        uint16_t duty   = atoi(argv[2]);
//
//        global_count  = (uint16_t)atoi(argv[3]);
//
//        LL_TIM_OC_SetCompareCH3(htim1.Instance, (uint16_t)(1000-duty));
//        if(!strcmp(operator, "CH3N"))
//        {
//            LOG_D("CH3N ok!");
//            HAL_TIMEx_PWMN_Start_IT(&htim1,TIM_CHANNEL_3);
//        }
//        else if(!strcmp(operator, "CH3P"))
//        {
//            LOG_D("CH3P ok!");
//            HAL_TIM_PWM_Start_IT(&htim1,TIM_CHANNEL_3);
//        }
//        else if(!strcmp(operator, "CH3NP"))
//        {
//            LOG_D("CH3NP ok!");
//            HAL_TIM_PWM_Start_IT(&htim1,TIM_CHANNEL_3);
//            HAL_TIMEx_PWMN_Start_IT(&htim1,TIM_CHANNEL_3);
//        }
//    }
//
//    uint16_t count   = atoi(argv[3]);
//    if(count < 10000)
//    {
//        rt_thread_mdelay(count);
//        LL_TIM_OC_SetCompareCH3(htim1.Instance, 1000);
//    }
//}
//MSH_CMD_EXPORT(pwmctrl, control PWM freq&duty);
//
//void pwmduty(uint8_t argc, char **argv)
//{
//
//#define CMD_PROBE_INDEX               0
//#define CMD_READ_INDEX                1
//#define CMD_WRITE_INDEX               2
//#define CMD_ERASE_INDEX               3
//#define CMD_RW_STATUS_INDEX           4
//#define CMD_BENCH_INDEX               5
//    size_t i = 0;
//    const char* sf_help_info[] = {
//            [CMD_PROBE_INDEX]     = "sf probe [spi_device]           - probe and init SPI flash by given 'spi_device'",
//            [CMD_READ_INDEX]      = "sf read addr size               - read 'size' bytes starting at 'addr'",
//            [CMD_WRITE_INDEX]     = "sf write addr data1 ... dataN   - write some bytes 'data' to flash starting at 'addr'",
//            [CMD_ERASE_INDEX]     = "sf erase addr size              - erase 'size' bytes starting at 'addr'",
//            [CMD_RW_STATUS_INDEX] = "sf status [<volatile> <status>] - read or write '1:volatile|0:non-volatile' 'status'",
//            [CMD_BENCH_INDEX]     = "sf bench                        - full chip benchmark. DANGER: It will erase full chip!",
//    };
////控制pwm输出通道、频率（暂不控制，定频10Khz）、占空比、重复次数
//    if (argc < 4)
//    {
//        rt_kprintf("Usage:\n");
//        for (i = 0; i < sizeof(sf_help_info) / sizeof(char*); i++)
//        {
//            rt_kprintf("%s\n", sf_help_info[i]);
//        }
//        rt_kprintf("\n");
//    }
//    else
//    {
//        const char *operator = argv[1];
//        uint16_t duty   = atoi(argv[2]);
//
//        global_count  = (uint16_t)atoi(argv[3]);
//
//        LL_TIM_OC_SetCompareCH3(htim1.Instance, (uint16_t)(1000-duty));
//    }
//
//    uint16_t count   = atoi(argv[3]);
//    if(count < 10000)
//    {
//        rt_thread_mdelay(count);
//        LL_TIM_OC_SetCompareCH3(htim1.Instance, 1000);
//    }
//}
//MSH_CMD_EXPORT(pwmduty, control PWM freq&duty);

//void soongtest(void)
//{
//    LL_TIM_OC_SetCompareCH3( htim1.Instance, 100 );
//    LOG_D("ssss");
//}
//MSH_CMD_EXPORT(soongtest, soongBQ test shell);

